home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 80 / CD Actual 80 Julio-Agosto 2003.iso / Linux / LinuxGazette / lg / issue91 / misc / mathew / code / pvcl.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-05-20  |  33.8 KB  |  1,516 lines

  1. /*  Copyright (C) 2003 Cherry George Mathew <cherry@freeshell.org>
  2.  
  3.     This program is free software; you can redistribute it and/or modify
  4.     it under the terms of the GNU General Public License as published by
  5.     the Free Software Foundation; either version 2 of the License, or
  6.     (at your option) any later version.
  7.     
  8.     This program is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.     GNU General Public License for more details.
  12.     
  13.     You should have received a copy of the GNU General Public License
  14.     along with this program; if not, write to the Free Software
  15.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17.  
  18. #include <linux/version.h> 
  19. #include <linux/module.h>
  20. #include <linux/delay.h>
  21. #include <linux/errno.h>
  22. #include <linux/fs.h>
  23. #include <linux/kernel.h>
  24. #include <linux/sched.h>
  25. #include <linux/interrupt.h>
  26. #include <linux/kdev_t.h>
  27. #include "pvcard.h"
  28. #include "pvcl.h" 
  29. #include "pvproc.h"
  30. #include <asm/io.h>
  31. #include <asm/bitops.h>
  32.  
  33. /* const declarations and static allocations */
  34.  
  35. /* card ids ends with vendor id as marker. Number of cards is defined \
  36.  * as MAX_CARDS. Will add PCI_DEVICE_ID_CIRRUS_5465 Later.
  37.  */
  38. const int clgd54xx_card_id[]={PCI_DEVICE_ID_CIRRUS_5480,\
  39.                   PCI_DEVICE_ID_CIRRUS_5446,\
  40.                   PCI_VENDOR_ID_CIRRUS};
  41.  
  42. /* Decided against kmalloc for the moment. Would probably be efficient
  43.  * if we dealt with stuff like multiple cards, etc. not for the moment,
  44.  * though.
  45.  */
  46.  
  47.  
  48. /* Default max screen size hardcoded to ???? */
  49. static struct video_buffer vbuf_s = { 
  50. };
  51.  
  52. static struct video_picture vpict_s;
  53.  
  54. /* TODO: Chroma keying.....Default _no_ chromakeying bcos xawtv has no
  55.  *   support for it with V4L1. Someday.... Sigh ......*/
  56.  
  57. static struct video_window vwin_s = { 
  58. /*      chromakey:  GD_CHROMA_KEY,  */
  59. /*       flags:      VIDEO_WINDOW_CHROMAKEY   */
  60. };
  61.  
  62. /* Tuner properties hardcoded. */
  63. static struct video_tuner vtun_s = {
  64.     name:        "Television",
  65.     rangelow:    0,
  66.     rangehigh:   0x7FFFFFFF,
  67.     flags:       VIDEO_TUNER_PAL, 
  68.     mode:        VIDEO_MODE_PAL
  69. };
  70.  
  71. /* Single channel support at the moment. S-Video and Composite ignored. */
  72. static struct video_channel vchan_s = {
  73.     name:        "Television",
  74.     tuners:      1,
  75.     flags:       VIDEO_VC_TUNER | VIDEO_VC_AUDIO,
  76.     type:        VIDEO_TYPE_TV,
  77.     norm:        VIDEO_MODE_PAL
  78. };
  79.  
  80. static struct gd_status_t dstat_s = { 
  81.     vbuf_p:     &vbuf_s,
  82.     vwin_p:     &vwin_s,
  83.     vtun_p:     &vtun_s,
  84.     vchan_p:    &vchan_s,
  85.     vpict_p:    &vpict_s,
  86. };
  87.  
  88. /* Initializing a new adapter named clgd54xx. Right now, we'll make do 
  89.    with a static declaration. Not good enough for driving multiple cards.
  90. */
  91.  
  92.  
  93. static struct clgd54xx_card clgd54xx_card_info = {
  94.     spun_lock:    SPIN_LOCK_UNLOCKED,
  95.     drv_stat_p:   &dstat_s,
  96.     model:        PVCLPP_COMBO
  97. };
  98.  
  99. static struct i2c_algo_bit_data clgd54xx_bitbang_adap = {
  100.     data:         &clgd54xx_card_info,
  101.     setsda:       gd54xx_setsda,
  102.     setscl:       gd54xx_setscl,
  103.     getsda:       gd54xx_getsda,
  104.     getscl:       gd54xx_getscl,
  105.     udelay:       16,
  106.     mdelay:       10,
  107.     timeout:      200,
  108. };
  109.  
  110. static struct i2c_adapter clgd54xx_adap = {
  111.     name:        "clgd54xx",
  112.  
  113.     /* Now make i2c_adapter->algo_data point to our 
  114.      * i2c_algo_bit_data , ie; link adapter and algo.
  115.      */
  116.  
  117.     id:          I2C_ALGO_BIT | I2C_HW_B_BT848,
  118.     algo_data:   &clgd54xx_bitbang_adap,
  119. };
  120.  
  121. /* variable declarations and initializations */
  122.  
  123. unsigned int debug = 0;
  124. unsigned int re_entry = 0;
  125.  
  126. /* Adapter - Low level functions  */
  127.  
  128. /* Note:
  129.  * 5480 and 5446B can use either MMIO or PIO
  130.  * 5446A must use PIO
  131.  * 5465 must use MMIO
  132.  */
  133.  
  134. unsigned io_readb(unsigned port)
  135. {
  136.     vprintk("io_io_read on port %p\n", (char *) port);
  137.     return inb(port);
  138. }
  139.  
  140. void io_writeb(unsigned data, unsigned port)
  141. {
  142.     vprintk("io_io_write on port %p\n", (char *) port);
  143.     outb(data, port);
  144.  
  145. /***************  TODO: IMPLEMENT PCI MEM MAPPING *****************
  146.  
  147.  
  148. unsigned m_io_readb_proc(unsigned port)
  149. {
  150.     vprintk("m_io_read on port %p\n", (char *) port);
  151.     return readb(port);
  152. }
  153.  
  154. void m_io_writeb_proc(unsigned data, unsigned port)
  155. {
  156.     vprintk("m_io_write on port %p\n", (char *) port);
  157.     writeb(data, port);
  158. }
  159.  
  160. *************************************************************************/
  161. void gd_write_sr(struct clgd54xx_card *card_p,unsigned char datum,unsigned reg) 
  162. {
  163.     spin_lock_irqsave(&card_p->spun_lock, card_p->spinflags);
  164.     io_writeb(reg, card_p->gd_io_base + GD_SR_OFFSET); 
  165.     io_writeb(datum, card_p->gd_io_base + GD_SR_OFFSET + 1);
  166.     spin_unlock_irqrestore(&card_p->spun_lock, card_p->spinflags);
  167.  
  168. }
  169.  
  170.  
  171. void gd_write_gr(struct clgd54xx_card *card_p, unsigned char datum,unsigned reg) 
  172.         spin_lock_irqsave(&card_p->spun_lock,card_p->spinflags);
  173.     io_writeb(reg, card_p->gd_io_base + GD_GR_OFFSET); 
  174.     io_writeb(datum, card_p->gd_io_base + GD_GR_OFFSET + 1);
  175.     spin_unlock_irqrestore(&card_p->spun_lock,card_p->spinflags);
  176.  
  177. }
  178.  
  179. void gd_write_cr(struct clgd54xx_card *card_p, unsigned char datum,unsigned reg) 
  180. {
  181.         spin_lock_irqsave(&card_p->spun_lock, card_p->spinflags);
  182.     io_writeb(reg, card_p->gd_io_base + GD_CR_OFFSET);
  183.     io_writeb(datum, card_p->gd_io_base + GD_CR_OFFSET + 1);
  184.     spin_unlock_irqrestore(&card_p->spun_lock,card_p->spinflags);
  185.  
  186. }
  187.  
  188. unsigned gd_read_sr(struct clgd54xx_card *card_p, unsigned reg) 
  189. {
  190.     unsigned value;
  191.     spin_lock_irqsave(&card_p->spun_lock,card_p->spinflags);
  192.     io_writeb(reg, card_p->gd_io_base + GD_SR_OFFSET);
  193.     value = io_readb(card_p->gd_io_base + GD_SR_OFFSET + 1);
  194.     spin_unlock_irqrestore(&card_p->spun_lock,card_p->spinflags);
  195.     return value;
  196. }
  197.  
  198. unsigned gd_read_gr(struct clgd54xx_card *card_p, unsigned reg)
  199. {
  200.     unsigned value;
  201.         spin_lock_irqsave(&card_p->spun_lock, card_p->spinflags);
  202.     io_writeb(reg, card_p->gd_io_base + GD_GR_OFFSET);
  203.     value = io_readb(card_p->gd_io_base + GD_GR_OFFSET + 1);
  204.     spin_unlock_irqrestore(&card_p->spun_lock,card_p->spinflags);
  205.     return value;
  206. }
  207.  
  208. unsigned gd_read_cr(struct clgd54xx_card *card_p, unsigned reg)
  209. {
  210.     unsigned value;
  211.     spin_lock_irqsave(&card_p->spun_lock, card_p->spinflags);
  212.     io_writeb(reg, card_p->gd_io_base + GD_CR_OFFSET); 
  213.     value = io_readb(card_p->gd_io_base + GD_CR_OFFSET + 1);
  214.     spin_unlock_irqrestore(&card_p->spun_lock, card_p->spinflags);
  215.     return value;
  216. }
  217.  
  218.  
  219. void gd54xx_setsda (void *bit_adap_dat, int state)
  220. {
  221.     struct clgd54xx_card *data=bit_adap_dat;
  222.  
  223.     /* Switch on I2C interface */
  224.     set_bit(6, &data->i2c_state);
  225.  
  226.     /* Set/Clear bit */ 
  227.     state ? set_bit(1, &(data->i2c_state)) : clear_bit(1, &(data->i2c_state));
  228.  
  229.     gd_write_sr(data, data->i2c_state, 0x8);
  230. }
  231.  
  232. void gd54xx_setscl (void *bit_adap_dat, int state)
  233. {
  234.     struct clgd54xx_card *data=bit_adap_dat;
  235.  
  236.     set_bit(6, &data->i2c_state);
  237.     state ? set_bit(0, &(data->i2c_state)) : clear_bit(0, &(data->i2c_state));
  238.  
  239.     gd_write_sr(data, data->i2c_state, 0x8);
  240. }
  241.  
  242. int gd54xx_getsda (void *bit_adap_dat)
  243. {
  244.     struct clgd54xx_card *data=bit_adap_dat;
  245.  
  246.     return (((data->i2c_state = gd_read_sr(data, 0x8)) >>7)&0x1);
  247.  
  248.     return 0;
  249. }
  250.  
  251. int gd54xx_getscl (void *bit_adap_dat)
  252. {
  253.     struct clgd54xx_card *data=bit_adap_dat;
  254.     return (((data->i2c_state = gd_read_sr(data, 0x8)) >>2)&0x1);
  255.     return 0;
  256. }
  257.  
  258. /* Adapter functions - high level */
  259.  
  260. int i2c_clgd54xx_init_adapter(struct clgd54xx_card *card_p, 
  261.                   struct i2c_adapter * adap,
  262.                   struct i2c_algo_bit_data * bitadap)
  263. {
  264.  
  265.     /* Let's initialize some of the data structures.
  266.      * First plug in card adapter and card bit bang algo
  267.      * into card info.
  268.      */
  269.  
  270.     card_p->clgd54xx_adapter_p = adap;
  271.     card_p->clgd54xx_bitbang_adapter_p = bitadap;
  272.  
  273.     return     i2c_bit_add_bus(card_p->clgd54xx_adapter_p);
  274.  
  275. }
  276.  
  277. int i2c_clgd54xx_cleanup_adapter(struct clgd54xx_card *card_p){
  278.  
  279.     return i2c_bit_del_bus(card_p->clgd54xx_adapter_p);
  280. }
  281.  
  282. int i2c_clgd54xx_probe_card(struct clgd54xx_card *card_p)
  283. {
  284.     card_p->gd_io_base=0;
  285.     
  286.     /* Memory Mapped IO not supported at the moment.
  287.      * This driver won't work for multiple cards.
  288.      */
  289.     return 0;
  290. }
  291.  
  292. int i2c_clgd54xx_find_card(struct clgd54xx_card *card_p){
  293.     
  294.         struct pci_dev *dev = NULL;
  295.     int loop_count=0;
  296.     do{
  297.         if ((dev = pci_find_device(clgd54xx_card_id[MAX_CARDS],clgd54xx_card_id[loop_count], dev))) {
  298.  
  299.             printk(KERN_INFO
  300.                    "pvcl: Found %s\n", dev->name);
  301.             card_p->clgd54xx_pci_dev_p = dev;
  302.             card_p->clgd54xx_pci_dev_id =
  303.                 clgd54xx_card_id[loop_count];
  304.             
  305.             printk(KERN_INFO
  306.                    "pvcl: Detected %dMB video ram.\n",
  307.                    gd_count_ram(card_p));
  308.             
  309.             return 0;
  310.         }
  311.         loop_count++;
  312.     } while(clgd54xx_card_id[loop_count]!=clgd54xx_card_id[MAX_CARDS]);
  313.  
  314.     printk(KERN_WARNING
  315.            "pvcl: Sorry. Could not find a Cirrus Logic Chip.\n");
  316.     return -ENODEV;
  317.  
  318. }
  319.  
  320.  
  321. /*
  322.  *  gd_count_ram() is hacked from gd5480.c from the xtv package.
  323.  *  xtv is copyrighted to Itai Nahshon <nahshon@actcom.co.il>.
  324.  *  Used with permission from the author.
  325.  */
  326.  
  327.  
  328. int
  329. gd_count_ram(struct clgd54xx_card *card_p)
  330. {
  331.     int videoram = 1;
  332.     int SR0F, SR17;
  333.  
  334.     unsigned short chip_type = card_p->clgd54xx_pci_dev_id;
  335.  
  336.     switch (chip_type) {
  337.         case PCI_DEVICE_ID_CIRRUS_5446:
  338.         videoram = 1;
  339.     
  340.         SR0F = gd_read_sr(card_p, 0x0F);
  341.         SR17 = gd_read_sr(card_p, 0x17);
  342.         if ((SR0F & 0x18) == 0x18) {
  343.             if(SR0F & 0x80) {
  344.                 if(SR17 & 0x80)
  345.                     videoram = 2;
  346.                 else if(SR17 & 0x02)
  347.                     videoram = 3;
  348.                 else
  349.                     videoram = 4;
  350.             }
  351.             else {
  352.                 if((SR17 & 80) == 0)
  353.                     videoram = 2;
  354.             }
  355.         }
  356.         break;
  357.         
  358.     case PCI_DEVICE_ID_CIRRUS_5480:
  359.         videoram = 1;
  360.         SR0F = gd_read_sr(card_p, 0x0F);
  361.         if ((SR0F & 0x18) == 0x18) {    /* 2 or 4 MB */
  362.             videoram = 2;
  363.             if (SR0F & 0x80)    /* Second bank enable */
  364.                 videoram = 4;
  365.         }
  366.         break;
  367.         
  368.     case PCI_DEVICE_ID_CIRRUS_5465:
  369.         videoram = 4;
  370.         break;
  371.     }
  372.  
  373.     card_p->vram = videoram;
  374.     return videoram;
  375. }
  376.  
  377.  
  378. int __init i2c_clgd54xx_init(struct clgd54xx_card *card_p,
  379.                  struct i2c_adapter *adap,
  380.                  struct i2c_algo_bit_data *bitadap)
  381. {
  382.     int ret_val;
  383.  
  384.     /* This adapter is non-re-entrant at the moment */
  385.  
  386.     if(re_entry) return -EBUSY;
  387.  
  388.     re_entry = 1;
  389.  
  390.     if( (ret_val = i2c_clgd54xx_find_card(card_p)) ){
  391.         return ret_val;
  392.     }
  393.     
  394.     if( (ret_val = i2c_clgd54xx_probe_card(card_p)) ){
  395.         return ret_val;
  396.     }
  397.     
  398.     if( (ret_val = i2c_clgd54xx_init_adapter(card_p, adap, bitadap)) ){
  399.         return ret_val;
  400.     }
  401.     
  402.     return ret_val;
  403. }
  404.  
  405. int __init i2c_clgd54xx_cleanup(struct clgd54xx_card *card_p)
  406. {
  407.     re_entry=0;
  408.  
  409.     return i2c_clgd54xx_cleanup_adapter( card_p );
  410.     
  411. }
  412.  
  413. /* i2c client support */
  414. void do_client_ioctl(struct file *file, unsigned int cmd, void *arg)
  415. {
  416.     struct clgd54xx_card  *card_p = file->private_data;
  417.     struct i2c_adapter *adap = card_p->clgd54xx_adapter_p;
  418.     
  419.     int i;
  420.     
  421.         for (i = 0; i < I2C_CLIENT_MAX; i++) {
  422.                 if (NULL == adap->clients[i])
  423.                         continue;
  424.                 if (NULL == adap->clients[i]->driver->command)
  425.                         continue;
  426.                 adap->clients[i]->driver->command(
  427.                              adap->clients[i],cmd,arg);
  428.         }
  429.  
  430.     
  431. }
  432.  
  433. /* VGA support functions. */
  434.  
  435. /* gd_bit_copy() - used for copying data to/from VGA registers */
  436.  
  437. void gd_bit_copy(unsigned long * dest, int dest_start,  
  438.          unsigned long * src, int src_start, int src_stop)
  439. {
  440.     for(; src_start<= src_stop; src_start++, dest_start++)
  441.         {
  442.             if(test_bit(src_start, src))
  443.                 set_bit(dest_start, dest);
  444.             else
  445.                 clear_bit(dest_start, dest);
  446.         }
  447.                    
  448. }
  449.  
  450. void gd_enable_window(struct clgd54xx_card * card_p)
  451. {
  452.     unsigned long CR3E, CR50, CR51, CR58, CR5C;
  453.  
  454.     CR3E = gd_read_cr(card_p, 0x3e);
  455.     CR50 = gd_read_cr(card_p, 0x50);
  456.     CR51 = gd_read_cr(card_p, 0x51);
  457.     CR58 = gd_read_cr(card_p, 0x58);
  458.     CR5C = gd_read_cr(card_p, 0x5c);
  459.  
  460.     /* Disable Teletext CR5C[7] = 0 */
  461.      clear_bit(7,  &CR5C); 
  462.  
  463. /*     Capture all frames CR50[7], CR50[2], CR58[6] = 0,0,0 */
  464.  
  465.      clear_bit(7, &CR50); 
  466.      clear_bit(2, &CR50); 
  467.     clear_bit(6, &CR58); 
  468.     
  469.     /*    Set Capture input to VPORT CR50[1:0] = 11  */
  470.  
  471.     set_bit(0, &CR50);           /* Falling edge of HREF ends  */  
  472.     set_bit(1, &CR50);           /* capture line. */
  473.     
  474.     /* Enable Capture CR51[3] = 1 */
  475.       set_bit(3, &CR51); 
  476.     
  477.     /* Enable Video Window CR3E[0] = 1 */
  478.     set_bit(0, &CR3E);
  479.  
  480.     gd_write_cr(card_p, CR5C, 0x5c);
  481.     gd_write_cr(card_p, CR58, 0x58);
  482.     gd_write_cr(card_p, CR51, 0x51);
  483.     gd_write_cr(card_p, CR50, 0x50);
  484.     gd_write_cr(card_p, CR3E, 0x3e);
  485.  
  486. }
  487.  
  488. void gd_disable_window(struct clgd54xx_card * card_p)
  489. {
  490.     unsigned long CR3E, CR50, CR51;
  491.      
  492.     CR3E = gd_read_cr(card_p, 0x3e);
  493.     CR50 = gd_read_cr(card_p, 0x50);
  494.     CR51 = gd_read_cr(card_p, 0x51);
  495.  
  496.  
  497.     /*     Disable Capture CR51[3] = 0 */
  498.       clear_bit(3, &CR51);  
  499.  
  500.     /*    Reset Capture input to standard feature 
  501.         connector CR50[1:0] = 11  */
  502.  
  503.     clear_bit(0, &CR50);           /* Falling edge of HREF ends capture */
  504.     clear_bit(1, &CR50);  
  505.  
  506.     /* Disable Video Window CR3E[0] = 0 */
  507.     clear_bit(0, &CR3E);
  508.  
  509.  
  510.     gd_write_cr(card_p, CR51, 0x51);
  511.     gd_write_cr(card_p, CR50, 0x50);
  512.     gd_write_cr(card_p, CR3E, 0x3e);
  513. }
  514.  
  515. void gd_set_vbuf1(struct clgd54xx_card * card_p, unsigned long ptr)
  516. {
  517.         unsigned long CR3A, CR3B, CR3C, CR5D;
  518.  
  519.  
  520.     CR3A = gd_read_cr(card_p, 0x3a);
  521.     CR3B = gd_read_cr(card_p, 0x3b);
  522.     CR3C = gd_read_cr(card_p, 0x3c);
  523.     CR5D = gd_read_cr(card_p, 0x5d);
  524.  
  525.     /* CR5D[3:2] = ptr[1:0]  */
  526.  
  527.     gd_bit_copy( &CR5D, 2, &ptr, 0, 1);
  528.  
  529.     /* CR3A = ptr[9:2] */
  530.  
  531.     gd_bit_copy( &CR3A, 0, &ptr, 2, 9);
  532.  
  533.     
  534.     /* CR3B = ptr[17:10] */
  535.  
  536.     gd_bit_copy(&CR3B, 0, &ptr, 10, 17);
  537.  
  538.     /* CR3C[3:0] = ptr[21:18] */
  539.  
  540.     gd_bit_copy(&CR3C, 0, &ptr, 18, 21);
  541.  
  542.     gd_write_cr(card_p, CR3A, 0x3a);
  543.     gd_write_cr(card_p, CR3B, 0x3b);
  544.     gd_write_cr(card_p, CR3C, 0x3c);
  545.     gd_write_cr(card_p, CR5D, 0x5d);
  546.  
  547. }
  548.  
  549. void gd_set_vbuf2(struct clgd54xx_card * card_p, unsigned long ptr)
  550. {
  551.         unsigned long CR59, CR5A, CR58, CR5D;
  552.  
  553.     CR59 = gd_read_cr(card_p, 0x59);
  554.     CR5A = gd_read_cr(card_p, 0x5a);
  555.     CR58 = gd_read_cr(card_p, 0x58);
  556.     CR5D = gd_read_cr(card_p, 0x5d);
  557.  
  558.     /* CR5D[3:2] = ptr[1:0] */
  559.  
  560.     gd_bit_copy(&CR5D, 2, &ptr, 0, 1);
  561.  
  562.     /* CR59 = ptr[9:2]  */
  563.  
  564.     gd_bit_copy(&CR59, 0, &ptr, 2, 9);
  565.     
  566.     /* CR5A = ptr[17:10] */
  567.  
  568.     gd_bit_copy(&CR5A, 0, &ptr, 10, 17);
  569.  
  570.     /* CR58[3:0] = ptr[21:18] */
  571.  
  572.     gd_bit_copy(&CR58, 0, &ptr, 18, 21);
  573.  
  574.     gd_write_cr(card_p, CR59, 0x59);
  575.     gd_write_cr(card_p, CR5A, 0x5a);
  576.     gd_write_cr(card_p, CR58, 0x58);
  577.     gd_write_cr(card_p, CR5D, 0x5d);
  578.  
  579. }
  580.  
  581. unsigned long gd_get_vbuf1(struct clgd54xx_card * card_p)
  582. {
  583.         unsigned long CR3A, CR3B, CR3C, CR5D;
  584.     unsigned long ptr;
  585.  
  586.     CR3A = gd_read_cr(card_p, 0x3a);
  587.     CR3B = gd_read_cr(card_p, 0x3b);
  588.     CR3C = gd_read_cr(card_p, 0x3c);
  589.     CR5D = gd_read_cr(card_p, 0x5d);
  590.  
  591.     /*  ptr[1:0]  = CR5D[3:2] */
  592.     ptr = 0;
  593.     gd_bit_copy( &ptr, 0, &CR5D, 2, 3);
  594.  
  595.     /*  ptr[9:2] = CR3A */
  596.  
  597.     gd_bit_copy( &ptr, 2, &CR3A, 0, 7);
  598.  
  599.     
  600.     /* ptr[17:10] = CR3B */
  601.  
  602.     gd_bit_copy(&ptr, 10, &CR3B, 0, 7);
  603.  
  604.     /* ptr[21:18] = CR3C[3:0] */
  605.  
  606.     gd_bit_copy(&ptr, 18, &CR3C, 0, 3);
  607.  
  608.     return ptr;
  609.  
  610. }
  611.  
  612.  
  613. unsigned long gd_get_vbuf2(struct clgd54xx_card * card_p)
  614. {
  615.         unsigned long CR59, CR5A, CR58, CR5D;
  616.     unsigned long ptr;
  617.  
  618.     CR59 = gd_read_cr(card_p, 0x59);
  619.     CR5A = gd_read_cr(card_p, 0x5a);
  620.     CR58 = gd_read_cr(card_p, 0x58);
  621.     CR5D = gd_read_cr(card_p, 0x5d);
  622.  
  623.     /* ptr[1:0] = CR5D[3:2] */
  624.     ptr = 0;
  625.     gd_bit_copy(&ptr, 0, &CR5D, 2, 3);
  626.  
  627.     /* ptr[9:2] = CR59 */
  628.  
  629.     gd_bit_copy(&ptr, 2, &CR59, 0, 7);
  630.  
  631.     /* ptr[17:10] = CR5A */
  632.  
  633.     gd_bit_copy(&ptr, 10, &CR5A, 0, 7);
  634.  
  635.     /* ptr[21:18] = CR58[3:0] */
  636.     
  637.     gd_bit_copy(&ptr, 18, &CR58, 0, 3);
  638.     return ptr;
  639.  
  640. }
  641.  
  642. void gd_set_pitch(struct clgd54xx_card * card_p, unsigned long offset)
  643. {
  644.     unsigned long CR3C, CR3D;
  645.     
  646.     CR3C = gd_read_cr(card_p, 0x3c);
  647.     CR3D = gd_read_cr(card_p, 0x3d);
  648.  
  649.     /* CR3C[5] = offset[11], CR3D = offset[10:3] */
  650.  
  651.     gd_bit_copy(&CR3C, 5, &offset ,11, 11);
  652.  
  653.     gd_bit_copy(&CR3D, 0, &offset, 3, 10);
  654.  
  655.     gd_write_cr(card_p, CR3C, 0x3c);
  656.     gd_write_cr(card_p, CR3D, 0x3d);
  657.  
  658. }
  659.  
  660.  
  661. unsigned long gd_get_pitch(struct clgd54xx_card * card_p)
  662. {
  663.  
  664.     unsigned long CR3C, CR3D;
  665.     unsigned long offset ;
  666.  
  667.  
  668.         CR3C = gd_read_cr(card_p, 0x3c);
  669.         CR3D = gd_read_cr(card_p, 0x3d);
  670.     
  671.     /* offset[11] = CR3C[5] , offset[10:3] = CR3D */
  672.     offset = 0;
  673.     gd_bit_copy(&offset, 11, &CR3C, 5, 5);
  674.     gd_bit_copy(&offset, 3, &CR3D, 0, 7);
  675.  
  676.     return offset;
  677. }
  678.  
  679.  
  680.  
  681. void gd_init_video( struct clgd54xx_card * card_p )
  682. {
  683.     unsigned long temp_reg;
  684.     unsigned long  CR31, CR32, CR3E, CR3F, CR50, CR51, CR56, 
  685.         CR57, CR58, CR5C, CR5E;
  686.  
  687. /*     unsigned long GRC, GRD; */
  688.  
  689.     CR31 = gd_read_cr(card_p, 0x31);
  690.     CR32 = gd_read_cr(card_p, 0x32);
  691.     CR3E = gd_read_cr(card_p, 0x3e);
  692.     CR3F = gd_read_cr(card_p, 0x3f);
  693.     CR50 = gd_read_cr(card_p, 0x50);
  694.     CR51 = gd_read_cr(card_p, 0x51);
  695.     CR56 = gd_read_cr(card_p, 0x56);
  696.     CR57 = gd_read_cr(card_p, 0x57);
  697.     CR58 = gd_read_cr(card_p, 0x58); /* Dependancy only on maxheight */
  698.     CR5C = gd_read_cr(card_p, 0x5c);
  699.     CR5E = gd_read_cr(card_p, 0x5e);
  700.  
  701.  
  702.     /*     GRC = gd_read_gr(card_p, 0x0c); */
  703.     /*     GRD = gd_read_gr(card_p, 0x0d); */
  704.  
  705.     /* Set the maximum scanlines to 512, we don't want 
  706.      *  wanton clipping. */
  707.  
  708.     temp_reg = 0xff;
  709.     gd_bit_copy(&CR57, 0, &temp_reg, 0, 7);
  710.     set_bit(5, &CR58);
  711.  
  712.     /* Luminance only capture disabled */
  713.     /* CR5C[5] = 0 */
  714.     
  715.     clear_bit(5, &CR5C);
  716.  
  717.     /* Count lines upto capture, set to zero */
  718.     /* CR56[4:0] = 0 */
  719.  
  720.     temp_reg = 0;
  721.     gd_bit_copy(&CR56, 0, &temp_reg, 0, 4);
  722.  
  723.     /* Non - Interlaced capture */
  724.     /* CR50[6] = 0 */
  725.  
  726.     clear_bit(6, &CR50);
  727.  
  728.     /* 8bits, VPort width */
  729.     /* CR50[4] = 0; */
  730.  
  731.     clear_bit(4, &CR50);
  732.  
  733.     /* Double clock capture */
  734.     /* CR50[3] = 1; */
  735.     
  736.     set_bit(3, &CR50);
  737.       
  738.  
  739.     /* Video Capture (Not Teletext) */
  740.     /* CR5C[7] = 0 */
  741.  
  742.     clear_bit(7, &CR5C);
  743.  
  744.     /* Capture Data Format - YUV 4:2:2 */
  745.     /* CR51[2:0] = 000 */
  746.  
  747.     clear_bit(0, &CR51);
  748.     clear_bit(1, &CR51);
  749.     clear_bit(2, &CR51);
  750.  
  751.     /* Display Data Format - YUV 4:2:2 */
  752.     /* CR3E[3:1] = 000 */
  753.     /* CR3F[4] = 0 */
  754.  
  755.     clear_bit(1, &CR3E);
  756.     clear_bit(2, &CR3E);
  757.     clear_bit(3, &CR3E);
  758.     clear_bit(4, &CR3F);
  759.  
  760.     /* Double Buffer Control - Autoswitch */
  761.     /* CR5E[5:4] = 10 */
  762.  
  763.     clear_bit(4, &CR5E);
  764.     set_bit(5, &CR5E);
  765.  
  766.  
  767.     /* Set Zoom = 1:1 ie., ZoomX = ZoomY = 0 */
  768.     /* ZoomX = CR31, ZoomY = CR32 */
  769.     CR31 = CR32 = 0;
  770.     
  771.     /* Also, Zoom mode set to 1; ie; line replication, 
  772.      * in anticipation of chromakeying..
  773.      */
  774.     set_bit(4, &CR3E);
  775.  
  776.     /* Occlusion set to Colour Key, tagged compare (16 bit). */
  777.     /* CR1D[5:3] = 011 */
  778.  
  779.     /*     set_bit(3, &CR1D); */
  780.     /*     clear_bit(4, &CR1D); */
  781.     /*     clear_bit(5, &CR1D); */
  782.        
  783.  
  784.  
  785.     /* Set the Chroma key. */
  786.  
  787.     /*     GRC = 0; */
  788.     /*     GRD = GD_CHROMA_KEY; */
  789.        
  790.     /* Switch on Chromakeying */
  791.     /*     set_bit(7, &CR3E); */
  792.  
  793.     /*     gd_write_gr(card_p, GRC, 0x0c); */
  794.     /*     gd_write_gr(card_p, GRD, 0x0d); */
  795.  
  796.     gd_write_cr(card_p, CR50, 0x50);
  797.     gd_write_cr(card_p, CR51, 0x51);
  798.     gd_write_cr(card_p, CR56, 0x56);
  799.     gd_write_cr(card_p, CR57, 0x57);
  800.     gd_write_cr(card_p, CR58, 0x58); /* May be safely removed with Mx ht.*/
  801.     gd_write_cr(card_p, CR5C, 0x5c);
  802.     gd_write_cr(card_p, CR5E, 0x5e);
  803.     gd_write_cr(card_p, CR31, 0x31);
  804.     gd_write_cr(card_p, CR32, 0x32);
  805.     gd_write_cr(card_p, CR3E, 0x3e);
  806.     gd_write_cr(card_p, CR3F, 0x3f);
  807. }
  808.  
  809. void gd_get_window(struct clgd54xx_card * card_p,
  810.            struct video_window *winstruct,
  811.            struct video_buffer * vbuf)
  812. {
  813.     int depth;
  814.     unsigned long R1SZ, R1Adjust, R2SZ, R2Adjust, R2DSZ, WVS, WVE, WAO;
  815.      unsigned long CR33, CR34, CR35, CR36, CR37, CR38, CR39, CR5D;
  816.  
  817.     depth = (vbuf->depth == 32 ? 24 : vbuf->depth);
  818.         CR33 = gd_read_cr(card_p, 0x33);
  819.     CR34 = gd_read_cr(card_p, 0x34);
  820.     CR35 = gd_read_cr(card_p, 0x35);
  821.     CR36 = gd_read_cr(card_p, 0x36);
  822.     CR37 = gd_read_cr(card_p, 0x37);
  823.     CR38 = gd_read_cr(card_p, 0x38);
  824.     CR39 = gd_read_cr(card_p, 0x39);
  825.     CR5D = gd_read_cr(card_p, 0x5d);
  826.  
  827.  
  828.     /* R1SZ = CR36[1:0] CR33 */
  829.     R1SZ = 0;
  830.     gd_bit_copy(&R1SZ, 8, &CR36, 0, 1);
  831.     gd_bit_copy(&R1SZ, 0, &CR33, 0, 7);
  832.     
  833.     /* R1Adjust = CR5D[1:0] */
  834.  
  835.     R1Adjust = 0;
  836.     gd_bit_copy(&R1Adjust, 0, &CR5D, 0, 1);
  837.  
  838.     /* R2SZ = CR36[3:2] CR34 */
  839.     R2SZ = 0;
  840.     gd_bit_copy(&R2SZ, 8, &CR36, 2, 3);
  841.     gd_bit_copy(&R2SZ, 0, &CR34, 0, 7);
  842.  
  843.     /* R2Adjust = CR5D[5:4] */
  844.     R2Adjust = 0;
  845.     gd_bit_copy(&R2Adjust, 0, &CR5D, 4, 5);
  846.  
  847.     /* R2DSZ = CR36[5:4] CR35 */
  848.     R2DSZ = 0;
  849.     gd_bit_copy(&R2DSZ, 8, &CR36, 4, 5);
  850.     gd_bit_copy(&R2DSZ, 0, &CR35, 0, 7);
  851.  
  852.     /* WVS = CR39[1:0] CR37 */
  853.     WVS = 0;
  854.     gd_bit_copy(&WVS, 8, &CR39, 0, 1);
  855.     gd_bit_copy(&WVS, 0, &CR37, 0, 7);
  856.  
  857.     /* WVE = CR39[3:2] CR38 */
  858.     WVE = 0;
  859.     gd_bit_copy(&WVE, 8, &CR39, 2, 3);
  860.     gd_bit_copy(&WVE, 0, &CR38, 0, 7);
  861.  
  862.     WAO = 0;
  863.  
  864.     WAO = gd_get_pitch(card_p);
  865.  
  866.  
  867.     tprintk("gd_get_window() hardware registers read:\n
  868.                 depth = %d bpp \n
  869.                 R1SZ = %ld\n
  870.                 R1Adjust = %ld\n
  871.                 R2SZ = %ld\n 
  872.                 R2Adjust = %ld\n 
  873.                 R2DSZ = %ld\n 
  874.                 WVS=%ld\n WVE=%ld\n 
  875.                 WAO=%ld\n", depth,
  876.         R1SZ, R1Adjust, R2SZ, R2Adjust, R2DSZ, WVS, WVE, WAO);
  877.  
  878.     winstruct->x = R1SZ * 32 / depth + R1Adjust * 8 / depth;
  879.  
  880.     winstruct->width = R2SZ * 32 / depth + R2Adjust * 8 / depth;
  881.  
  882.     winstruct->y = WVS;
  883.     winstruct->height = WVE - WVS;
  884.  
  885. }
  886.  
  887.  
  888. void gd_set_window(struct clgd54xx_card * card_p,
  889.            struct video_window *winasked,
  890.            struct video_window *wingiven,
  891.            struct video_buffer *vbuf)
  892. {
  893.     int depth;
  894.     unsigned long R1SZ, R1Adjust, R2SZ, R2Adjust, R2DSZ, WVS, WVE, WAO;
  895.     unsigned ZOOMY, CR32;
  896.     unsigned long CR33, CR34, CR35, CR36, CR37, CR38, CR39, CR5D;
  897.  
  898.     depth = (vbuf->depth == 32 ? 24 : vbuf->depth);
  899.  
  900.     /* Safety Checks and clipping, for window borders. */
  901.  
  902.     winasked->x = winasked->x < 0 ?
  903.         0 : winasked->x;
  904.  
  905.     winasked->y = winasked->y < 0 ?
  906.         0 : winasked->y;
  907.         
  908.     winasked->width = (vbuf->width - winasked->x) < winasked->width ?
  909.         (vbuf->width - winasked->x) : winasked->width;
  910.  
  911.     winasked->height = (vbuf->height - winasked->y) < winasked->height ?
  912.         (vbuf->height - winasked->y) : winasked->height;
  913.  
  914.  
  915.     R1SZ = (winasked->x * depth) / 32;
  916.     R1Adjust = (winasked->x * depth - R1SZ * 32) / 8;
  917.     
  918.     R2SZ = (winasked->width * depth) / 32;
  919.     R2Adjust = (winasked->width * depth - R2SZ * 32) / 8;
  920.  
  921.     /*ugly hack. only tried on 24bpp and 16bpp eqn is. vbpp/gbpp * .5 */
  922.  
  923.     R2DSZ = R2SZ * 16 / depth + R2Adjust * 4 / depth;
  924.  
  925.     WVS = winasked->y;
  926.  
  927.     WVE = WVS + winasked->height;
  928.  
  929.     WAO = R2SZ * 4; 
  930.  
  931.     /* Zoom treatment. Doing zoom just for Vlines.
  932.      * Notes: Occlusion, ie; chromakeying and line interpolation 
  933.      * (in the case of zooming) are mutually exclusive. 
  934.      */
  935.     
  936.     if(wingiven->height < winasked->height)
  937.         {
  938.             ZOOMY = (wingiven->height * 256) / winasked->height - 5;
  939.             CR32 = ZOOMY;
  940.         }
  941.     else
  942.         CR32 = 0;      /* Don't want old Zoom values lying about. */
  943.             
  944.             
  945.  
  946.     /* CR36[1:0] CR33 = R1SZ */
  947.     gd_bit_copy(&CR36, 0, &R1SZ, 8, 9);
  948.     gd_bit_copy(&CR33, 0, &R1SZ, 0, 7);
  949.     
  950.     /* CR5D[1:0] = R1Adjust */
  951.     gd_bit_copy(&CR5D, 0, &R1Adjust, 0, 1);
  952.  
  953.     /* CR36[3:2] CR34 = R2SZ */
  954.     gd_bit_copy(&CR36, 2, &R2SZ, 8, 9);
  955.     gd_bit_copy(&CR34, 0, &R2SZ, 0, 7);
  956.  
  957.     /* CR5D[5:4] = R2Adjust */
  958.     
  959.     gd_bit_copy(&CR5D, 4, &R2Adjust, 0, 1);
  960.  
  961.     /* CR36[5:4] CR35 = R2DSZ */
  962.     
  963.     gd_bit_copy(&CR36, 4, &R2DSZ, 8, 9);
  964.     gd_bit_copy(&CR35, 0, &R2DSZ, 0, 7);
  965.  
  966.     /* CR39[1:0] CR37 = WVS */
  967.     
  968.     gd_bit_copy(&CR39, 0, &WVS, 8, 9);
  969.     gd_bit_copy(&CR37, 0, &WVS, 0, 7);
  970.  
  971.     /* CR39[3:2] CR38 = WVE */
  972.     
  973.     gd_bit_copy(&CR39, 2, &WVE, 8, 9);
  974.     gd_bit_copy(&CR38, 0, &WVE, 0, 7);
  975.  
  976.     /* CR36[5:4] CR35 = R2DSZ */
  977.  
  978.     gd_bit_copy(&CR36, 4, &R2DSZ, 8, 9);
  979.     gd_bit_copy(&CR35, 0, &R2DSZ, 0, 7);
  980.  
  981.     gd_set_pitch(card_p, WAO);
  982.  
  983.     tprintk("gd_set_window() hardware registers set to:\n
  984.                 R1SZ = %ld\n
  985.                 R1Adjust = %ld\n
  986.                 R2SZ = %ld\n 
  987.                 R2Adjust = %ld\n 
  988.                 R2DSZ = %ld\n 
  989.                 WVS=%ld\n WVE=%ld\n 
  990.                 WAO=%ld\n", 
  991.         R1SZ, R1Adjust, R2SZ, R2Adjust, R2DSZ, WVS, WVE, WAO);
  992.  
  993.           gd_write_cr(card_p, CR5D, 0x5d);  
  994.         gd_write_cr(card_p, CR39, 0x39);  
  995.         gd_write_cr(card_p, CR38, 0x38);  
  996.         gd_write_cr(card_p, CR37, 0x37);  
  997.         gd_write_cr(card_p, CR36, 0x36);  
  998.         gd_write_cr(card_p, CR35, 0x35);  
  999.         gd_write_cr(card_p, CR34, 0x34);  
  1000.         gd_write_cr(card_p, CR33, 0x33);  
  1001.         gd_write_cr(card_p, CR32, 0x32);  
  1002. }
  1003.  
  1004. /* returns clipped windows, according to available ram, with
  1005.  * video buffer starting as close to the end of video ram as possible.
  1006.  */
  1007.  
  1008. long gd_window_init(struct clgd54xx_card * card_p)
  1009. {
  1010.  
  1011.     int scrn_depth;
  1012.     unsigned long vbuf1_ptr, vbuf2_ptr, scrn_ht, scrn_wt, vram;
  1013.  
  1014.     vram = card_p->vram = gd_count_ram(card_p);
  1015.  
  1016.     scrn_ht = card_p->drv_stat_p->vbuf_p->height;
  1017.     scrn_wt = card_p->drv_stat_p->vbuf_p->width;
  1018.     scrn_depth = card_p->drv_stat_p->vbuf_p->depth;
  1019.     scrn_depth = scrn_depth == 32 ? 24 :scrn_depth;
  1020.  
  1021.     vbuf1_ptr = vram * 1048576 - 16384 - scrn_ht * scrn_wt * 2;
  1022.  
  1023.     /* Eeeks!!! No check for video data spilling over into framebuffer
  1024.      * space. OK folk. Get ready for full screen video! 
  1025.  
  1026.     if(vbuf1_ptr < (scrn_ht * scrn_wt * scrn_depth / 8)) return -1;
  1027.     
  1028.     */
  1029.  
  1030.     vbuf2_ptr = vbuf1_ptr;
  1031.  
  1032.     gd_init_video(card_p);
  1033.  
  1034.     printk("Marker \n");
  1035.  
  1036.     gd_set_vbuf1(card_p, vbuf1_ptr);
  1037.     gd_set_vbuf2(card_p, vbuf2_ptr);
  1038.  
  1039.     return vbuf2_ptr;
  1040.  
  1041. }
  1042.  
  1043. /* V4L Driver Callback functions */
  1044.  
  1045. static int pvcl_open(struct inode *inode, struct file *file)
  1046. {
  1047.  
  1048.     unsigned int minor = minor(inode->i_rdev);
  1049.     struct clgd54xx_card * card_p;
  1050.  
  1051.  
  1052.     file->private_data = &clgd54xx_card_info;
  1053.     card_p = file->private_data;
  1054.  
  1055.     do_client_ioctl(file, VPROC_INIT, &card_p->model);
  1056.  
  1057.     dprintk("pvcl_open called on minor %d\n", minor);
  1058.  
  1059.     return 0;
  1060. }
  1061.  
  1062. static int pvcl_release(struct inode *inode, struct file *file)
  1063. {
  1064.     file->private_data = NULL;
  1065.     
  1066.     dprintk("pvcl_release called.\n");
  1067.     return 0;
  1068. }
  1069.  
  1070. static int pvcl_do_ioctl(struct inode *inode, struct file *file,
  1071.                unsigned int cmd, void *arg)
  1072. {
  1073.  
  1074.     struct clgd54xx_card * card_p = file->private_data;
  1075.  
  1076.     switch(cmd) {
  1077.         
  1078.     case VIDIOCGCAP:
  1079.         {
  1080.             struct video_capability *cap = arg; 
  1081.             struct video_buffer *bufstat = 
  1082.                 card_p->drv_stat_p->vbuf_p;
  1083.  
  1084.             sprintf(cap->name, "pvcl");
  1085.             
  1086.             cap->type = VID_TYPE_TUNER | VID_TYPE_OVERLAY | 
  1087.                 VID_TYPE_FRAMERAM  | VID_TYPE_SCALES;
  1088.             
  1089.             cap->channels = 1; /* Just one channel for now. */
  1090.             cap->audios = 1;
  1091.  
  1092.             /* Max Screen Size reported by X11 via v4l-conf */
  1093.             cap->maxwidth = bufstat->width;    
  1094.             cap->maxheight = bufstat->height;  
  1095.             cap->minwidth = 32;  /* Hardcoded vpx 3225D specific */
  1096.             cap->minheight = 24;
  1097.             
  1098.             /* Hard Code PAL for the moment. */
  1099.  
  1100.             do_client_ioctl(file, VPROC_SET_CAP_MODE,
  1101.                     &card_p->drv_stat_p->vtun_p->mode);
  1102.  
  1103.             dprintk("VIDIOCGCAP called\n");
  1104.         
  1105.             return 0;
  1106.         }
  1107.  
  1108.     case VIDIOCGFBUF:
  1109.         {
  1110.             struct video_buffer *buf = arg;
  1111.             struct video_buffer *bufstat = 
  1112.                 card_p->drv_stat_p->vbuf_p;
  1113.  
  1114.             memcpy(buf, bufstat, sizeof(*buf));
  1115.  
  1116.             dprintk("VIDIOCGFBUF called. \n");
  1117.  
  1118.             return 0;
  1119.  
  1120.         }
  1121.         
  1122.     case VIDIOCSFBUF:
  1123.         {
  1124.             
  1125.             struct video_buffer *buf = arg;
  1126.             struct video_buffer *bufstat = 
  1127.                 card_p->drv_stat_p->vbuf_p;
  1128.  
  1129.  
  1130.             /* HEEEEEEEEEEEEELOOOOOOOOOOOOOOOO, Careful. Security 
  1131.                hole here!!!!!!!!!!! 
  1132.             */
  1133.             /* Security check disabled for now.
  1134.                if(!capable(CAP_SYS_ADMIN) &&
  1135.                !capable(CAP_SYS_RAWIO))
  1136.                return -EPERM;
  1137.             */
  1138.  
  1139.             memcpy(bufstat, buf, sizeof(*bufstat));
  1140.             
  1141.             dprintk("VIDIOCSFBUF called. \n");
  1142.             printk(KERN_INFO "client reports:\n
  1143.                               screen size: %dx%d @ %dbpp. 
  1144.                               %d bytesperline.\n.", 
  1145.                    bufstat->width, 
  1146.                    bufstat->height, 
  1147.                    bufstat->depth, 
  1148.                    bufstat->bytesperline);
  1149.  
  1150.             dprintk("Capture Buffer set to 0x%p", bufstat->base);
  1151.  
  1152.             /* Now that we've got the Screen Parms, 
  1153.              * we can inititialize the window */
  1154.  
  1155.             gd_window_init(card_p); 
  1156.  
  1157.             return 0;
  1158.         }
  1159.         
  1160.         
  1161.     case VIDIOCCAPTURE:
  1162.         {
  1163.             int *on = arg;
  1164.             struct video_buffer *bufstat = 
  1165.                 card_p->drv_stat_p->vbuf_p;
  1166.             
  1167.             if (*on) {
  1168.                 /* verify args */
  1169.                 if (NULL == bufstat->base)
  1170.                     return -EINVAL;
  1171.                 if (bufstat->width <32 ||
  1172.                     bufstat->height <24 ||
  1173.                     bufstat->width >800 ||
  1174.                     bufstat->height >600)
  1175.                     
  1176.                     return -EINVAL;
  1177.             }
  1178.  
  1179.             if(*on) {
  1180.                 
  1181.  
  1182.                 /* Tell vpx to switch on. `on' is dummy here.*/
  1183.  
  1184.                 do_client_ioctl(file, VPROC_START_CAPTURE, on);
  1185.                 gd_enable_window(card_p); 
  1186.                 
  1187.                 dprintk("VIDIOCCAPTURE: video window switched on. \n");
  1188.                 return 0;
  1189.             }
  1190.  
  1191.             else {
  1192.  
  1193.                 /* Tell vpx to stop capture. `on'  is dummy.*/
  1194.  
  1195.                 do_client_ioctl(file, VPROC_STOP_CAPTURE, on);
  1196.  
  1197.                 gd_disable_window(card_p); 
  1198.  
  1199.                 dprintk("VIDIOCCAPTURE: video window switched off. \n");
  1200.                 return 0;
  1201.             }
  1202.                 
  1203.         }
  1204.         
  1205.     case VIDIOCGWIN:
  1206.         {
  1207.             struct video_window *winarg = arg;
  1208.             struct video_window *winstat = 
  1209.                 card_p->drv_stat_p->vwin_p;
  1210.             
  1211.             memcpy(winarg, winstat, sizeof(*winarg));
  1212.  
  1213.             /* TODO: Need to get actual window parms from
  1214.              * hardware. Use gd_get_video_window()
  1215.              */
  1216.  
  1217.             dprintk("VIDIOCGWIN called. \n");
  1218.             return 0;
  1219.         }
  1220.  
  1221.  
  1222.     case VIDIOCSWIN:
  1223.         {
  1224.             struct video_window *winarg = arg;
  1225.                         struct video_window *winstat = 
  1226.                 card_p->drv_stat_p->vwin_p;
  1227.             struct video_buffer *bufstat = 
  1228.                 card_p->drv_stat_p->vbuf_p;
  1229.  
  1230.              memcpy(winstat, winarg, sizeof(*winstat));
  1231.  
  1232.  
  1233.             tprintk("VIDIOCSWIN recieved:\n 
  1234.                                 \t position:   %d, %d \n 
  1235.                                 \t dimensions: %d, %d \n",
  1236.                                 winstat->x,
  1237.                 winstat->y, 
  1238.                 winstat->width, 
  1239.                 winstat->height); 
  1240.  
  1241.             do_client_ioctl(file, VPROC_SET_WINDOW, winarg); 
  1242.  
  1243.             /* gd_set_window(card_p, app_wants, vproc_gives....) */
  1244.  
  1245.             gd_set_window(card_p, winstat, winarg, bufstat); 
  1246.  
  1247.             tprintk("gd_set_window() recieved:\n 
  1248.                                 \t position:   %d, %d \n 
  1249.                                 \t dimensions: %d, %d \n",
  1250.                                 winstat->x,
  1251.                 winstat->y, 
  1252.                 winstat->width, 
  1253.                 winstat->height); 
  1254.  
  1255.                gd_get_window(card_p, winstat, bufstat);   
  1256.  
  1257.             tprintk("gd_get_window returned: \n 
  1258.                                 \t position:   %d, %d \n 
  1259.                                 \t dimensions: %d, %d \n",
  1260.                                 winstat->x,
  1261.                 winstat->y, 
  1262.                 winstat->width, 
  1263.                 winstat->height); 
  1264.  
  1265.  
  1266.                         dprintk("VIDIOCSWIN called. \n");
  1267.                         return 0;
  1268.                 }
  1269.  
  1270.         /* Wrappers for tuner.c - hacked from bttv-driver.c 
  1271.            which is copyrighted to :
  1272.          
  1273.            Copyright (C) 1996,97,98 
  1274.            Ralph  Metzler <rjkm@thp.uni-koeln.de>,
  1275.            Marcus Metzler <mocm@thp.uni-koeln.de>,
  1276.            &
  1277.            (c) 1999-2002 Gerd Knorr <kraxel@bytesex.org>
  1278.  
  1279.         */
  1280.         
  1281.         case VIDIOCGTUNER:
  1282.         {
  1283.             struct video_tuner *v = arg;
  1284.             struct video_tuner *vstat = 
  1285.                 card_p->drv_stat_p->vtun_p;
  1286.  
  1287.             if (v->tuner) /* Only tuner 0 */
  1288.                 return -EINVAL;
  1289.  
  1290.             do_client_ioctl(file,cmd,v);
  1291.  
  1292.             /* tuner.c returns v->signal, ie; signal strength. */
  1293.             memcpy(v, vstat, sizeof(*v));
  1294.  
  1295.             dprintk("VIDIOCGTUNER has been called. \n");
  1296.             return 0;
  1297.  
  1298.         }                    
  1299.         
  1300.         case VIDIOCSTUNER:
  1301.         {
  1302.             struct video_tuner *v = arg;
  1303.             struct video_tuner *vstat = 
  1304.                 card_p->drv_stat_p->vtun_p;
  1305.  
  1306.             if (v->tuner) /* Only tuner 0 */
  1307.                 return -EINVAL;
  1308.             if (v->mode > VIDEO_MODE_PAL)
  1309.                 return -EINVAL;
  1310.             
  1311.             do_client_ioctl(file,cmd,v);
  1312.  
  1313.             vstat->mode = v->mode;
  1314.  
  1315.             dprintk("VIDIOCSTUNER has been called. \n");
  1316.  
  1317.             return 0;
  1318.         }
  1319.  
  1320.         case VIDIOCGFREQ:
  1321.         {
  1322.             unsigned long *freq = arg;
  1323.             *freq = card_p->drv_stat_p->freq;
  1324.             dprintk("VIDIOCGFREQ called.\n");
  1325.         
  1326.             return 0;
  1327.         }
  1328.         case VIDIOCSFREQ:
  1329.         {
  1330.             unsigned long *freq = arg;
  1331.  
  1332.             do_client_ioctl(file,cmd,freq);
  1333.             
  1334.             card_p->drv_stat_p->freq=*freq;
  1335.             dprintk("VIDIOCSFREQ called.\n");
  1336.  
  1337.             return 0;
  1338.         }
  1339.  
  1340.         case VIDIOCSCHAN:
  1341.         {
  1342.             struct video_channel *v = arg;
  1343.             struct video_tuner *vstat = card_p->drv_stat_p->vtun_p;
  1344.  
  1345.             if (v->channel >  0)
  1346.                 return -EINVAL;
  1347.  
  1348.             if(v->norm > VIDEO_MODE_PAL)
  1349.                 return -EINVAL;
  1350.  
  1351.             /* TODO: need to implement tv norms. 
  1352.              * Currently hardcoded
  1353.              * to PAL. See struct video_channel 
  1354.              * vchan_s decl above. */
  1355.  
  1356.             do_client_ioctl(file,cmd,v);
  1357.  
  1358.             memcpy(vstat, v , sizeof(*v));
  1359.             dprintk("VIDIOCSCHAN has been called. \n");
  1360.             return 0;
  1361.         }
  1362.         
  1363.         case VIDIOCGCHAN:
  1364.         {
  1365.             struct video_channel *v = arg;
  1366.             struct video_channel *chanstat = 
  1367.                 card_p->drv_stat_p->vchan_p;
  1368.  
  1369.             memcpy(v, chanstat, sizeof(*v));
  1370.  
  1371.             dprintk("VIDIOCGCHAN has been called. \n");
  1372.  
  1373.             return 0;
  1374.         }
  1375.  
  1376.         /* End bttv-driver.c wrappers. */
  1377.  
  1378.  
  1379.     case VIDIOCGPICT:
  1380.         {
  1381.             struct video_picture *vpict = arg;
  1382.             struct video_picture *vpictstat =
  1383.                 card_p->drv_stat_p->vpict_p;
  1384.  
  1385.             memcpy(vpict, vpictstat, sizeof(*vpict));
  1386.  
  1387.             dprintk("VIDIOCGPICT has been called. \n");
  1388.         }
  1389.  
  1390.  
  1391.     case VIDIOCSPICT:
  1392.         {
  1393.             struct video_picture *vpict = arg;
  1394.             struct video_picture *vpictstat =
  1395.                 card_p->drv_stat_p->vpict_p;
  1396.  
  1397.             memcpy(vpictstat, vpict, sizeof(*vpict));
  1398.  
  1399.             do_client_ioctl(file, VPROC_SET_PICTURE, vpictstat);
  1400.             
  1401.             dprintk("VIDIOCGPICT has been called. \n");
  1402.         }
  1403.     }    
  1404.     
  1405.     return -ENOIOCTLCMD;
  1406.     
  1407.  
  1408.     
  1409. }
  1410.  
  1411.  
  1412. static int pvcl_ioctl(struct inode *inode, struct file *file,
  1413.             unsigned int cmd, unsigned long arg)
  1414. {
  1415.     return video_usercopy(inode, file, cmd, arg, pvcl_do_ioctl);
  1416. }
  1417.  
  1418. static ssize_t pvcl_read(struct file *file, char *data,
  1419.                size_t count, loff_t *ppos)
  1420. {
  1421.     return 0;
  1422. }
  1423.  
  1424. static struct file_operations pvcl_fops =
  1425. {
  1426.     owner:      THIS_MODULE,
  1427.     open:       pvcl_open,
  1428.     release:    pvcl_release,
  1429.     ioctl:      pvcl_ioctl,
  1430.     llseek:     no_llseek,
  1431.     read:       pvcl_read
  1432. };
  1433.  
  1434. static struct video_device pvcl_video_dev =
  1435. {
  1436.     name:      "PVCL ver 0.1",
  1437.     type:       VID_TYPE_TUNER | VID_TYPE_OVERLAY |
  1438.                     VID_TYPE_FRAMERAM | VID_TYPE_SCALES,
  1439.     fops:       &pvcl_fops,
  1440.     minor:      -1
  1441. };
  1442.  
  1443.  
  1444. /* Device Registration */
  1445. static int __devinit pvcl_register_video(struct video_device * video_dev )
  1446. {
  1447.     if(video_register_device(video_dev, VFL_TYPE_GRABBER, 0)<0)
  1448.         return -1;
  1449.     printk(KERN_INFO "pvcl: registered device video\n");
  1450.  
  1451.     return 0;
  1452.  
  1453.  
  1454. }
  1455.  
  1456. static void __devexit pvcl_unregister_video(struct video_device * video_dev)
  1457. {
  1458.     video_unregister_device(video_dev);
  1459. }
  1460.  
  1461. static int pvcl_init_module(void)
  1462. {
  1463.     int retval;
  1464.  
  1465.     if( (retval = pvcl_register_video( &pvcl_video_dev)) ) return retval;
  1466.     if( (retval = i2c_clgd54xx_init(&clgd54xx_card_info, 
  1467.                     &clgd54xx_adap,
  1468.                     &clgd54xx_bitbang_adap)) )
  1469.         return retval;
  1470.  
  1471.     switch(debug)
  1472.         {
  1473.         case 1:
  1474.             {
  1475.                 printk(KERN_INFO "pvcl: Functional Debug messages enabled.\n");
  1476.                 break;
  1477.             }
  1478.         case 2:
  1479.             {
  1480.                 printk(KERN_INFO "pvcl: Debug messages enabled per function.\n");
  1481.                 break;
  1482.             }
  1483.         case 3:
  1484.             printk(KERN_INFO "pvcl: WARNING: Verbose Debugging enabled - kernel printk buffers may overflow.\n");
  1485.             break;
  1486.         }
  1487.  
  1488.  
  1489.     return retval;
  1490.  
  1491. }
  1492.  
  1493. static void pvcl_cleanup_module(void)
  1494. {
  1495.     i2c_clgd54xx_cleanup(&clgd54xx_card_info);
  1496.     pvcl_unregister_video(&pvcl_video_dev);
  1497. }
  1498.  
  1499. module_init(pvcl_init_module);
  1500. module_exit(pvcl_cleanup_module);
  1501.  
  1502. MODULE_PARM(debug,"i");
  1503. MODULE_PARM_DESC(debug,"debug messages, default 0, is don't debug.");
  1504.  
  1505. MODULE_DESCRIPTION("pvcl - v4l driver module for the pixelview combo tv plus");
  1506. MODULE_AUTHOR("Cherry George Mathew");
  1507. MODULE_LICENSE("GPL");
  1508.  
  1509. /*
  1510.  * Local variables:
  1511.  * c-basic-offset: 8
  1512.  * End:
  1513.  */
  1514.